package server

import (
	"context"
	"sync"
	"time"
)

// EventType 定义事件类型
type EventType string

// 定义系统中的事件类型
const (
	EventClientJoin       EventType = "client_join"        //加入事件
	EventClientLeave      EventType = "client_leave"       //离开事件
	EventMsgBroadcast     EventType = "msg_broadcast"      //广播消息事件
	EventChangePlayFile   EventType = "change_play_file"   //更改播放文件事件
	EventChangePlayState  EventType = "change_play_state"  //更改播放状态事件
	EventObjSync          EventType = "obj_sync"           //对象同步事件
	EventRoomOwnerChange  EventType = "room_owner_change"  //更改房主事件
	EventRoomOwnerRequest EventType = "room_owner_request" //请求房主事件
	EventRoomProgress     EventType = "room_progress"      //房间进度事件
	EventMultiObjSync     EventType = "multi_obj_sync"     //多对象同步事件
)

// Event 表示一个事件
type Event struct {
	Type   EventType
	Data   interface{}
	RoomID string
	Source string // 事件源（通常是客户端ID）
}

// EventListener 事件监听器接口
type EventListener interface {
	HandleEvent(ctx context.Context, event Event)
}

// EventBus 事件总线，负责事件的发布和订阅
type EventBus struct {
	listeners map[EventType]map[string]EventListener
	eventCh   chan Event
	ctx       context.Context
	cancel    context.CancelFunc
	mu        sync.RWMutex
	wg        sync.WaitGroup
}

// NewEventBus 创建一个新的事件总线
func NewEventBus() *EventBus {
	ctx, cancel := context.WithCancel(context.Background())
	bus := &EventBus{
		listeners: make(map[EventType]map[string]EventListener),
		eventCh:   make(chan Event, 100), // 缓冲通道，避免阻塞
		ctx:       ctx,
		cancel:    cancel,
	}

	// 启动事件处理循环
	bus.wg.Add(1)
	go bus.processEvents()

	return bus
}

// Subscribe 订阅特定类型的事件
func (eb *EventBus) Subscribe(eventType EventType, listenerID string, listener EventListener) {
	eb.mu.Lock()
	defer eb.mu.Unlock()

	if _, exists := eb.listeners[eventType]; !exists {
		eb.listeners[eventType] = make(map[string]EventListener)
	}

	eb.listeners[eventType][listenerID] = listener
}

// Unsubscribe 取消订阅特定类型的事件
func (eb *EventBus) Unsubscribe(eventType EventType, listenerID string) {
	eb.mu.Lock()
	defer eb.mu.Unlock()

	if listeners, exists := eb.listeners[eventType]; exists {
		delete(listeners, listenerID)
	}
}

// UnsubscribeAll 取消指定监听器的所有订阅
func (eb *EventBus) UnsubscribeAll(listenerID string) {
	eb.mu.Lock()
	defer eb.mu.Unlock()

	for eventType, listeners := range eb.listeners {
		delete(listeners, listenerID)

		// 如果该事件类型没有监听器了，清理该映射
		if len(listeners) == 0 {
			delete(eb.listeners, eventType)
		}
	}
}

// Publish 发布事件
func (eb *EventBus) Publish(event Event) {
	select {
	case eb.eventCh <- event:
		// 事件成功发送到通道
	case <-eb.ctx.Done():
		// 事件总线已关闭
	}
}

// processEvents 处理事件循环
func (eb *EventBus) processEvents() {
	defer eb.wg.Done()

	for {
		select {
		case event := <-eb.eventCh:
			eb.dispatchEvent(event)
		case <-eb.ctx.Done():
			return
		}
	}
}

// dispatchEvent 将事件分发给所有订阅者
func (eb *EventBus) dispatchEvent(event Event) {
	eb.mu.RLock()
	listeners, exists := eb.listeners[event.Type]
	eb.mu.RUnlock()

	if !exists {
		return
	}

	// 创建一个带有超时的上下文，确保事件处理不会无限阻塞
	ctx, cancel := context.WithTimeout(eb.ctx, defaultEventTimeout)
	defer cancel()

	// 复制监听器列表，避免在遍历过程中修改
	eb.mu.RLock()
	listenersCopy := make([]EventListener, 0, len(listeners))
	for _, listener := range listeners {
		listenersCopy = append(listenersCopy, listener)
	}
	eb.mu.RUnlock()

	// 并发处理事件
	var wg sync.WaitGroup
	for _, listener := range listenersCopy {
		wg.Add(1)
		go func(l EventListener) {
			defer wg.Done()
			l.HandleEvent(ctx, event)
		}(listener)
	}

	// 等待所有事件处理完成或上下文取消
	done := make(chan struct{})
	go func() {
		wg.Wait()
		close(done)
	}()

	select {
	case <-done:
		// 所有事件处理完成
	case <-ctx.Done():
		// 超时或上下文取消
	}
}

// Close 关闭事件总线
func (eb *EventBus) Close() {
	eb.cancel()
	eb.wg.Wait()
	close(eb.eventCh)
}

// 默认事件处理超时时间
const defaultEventTimeout = 2 * time.Second
